#include "../pch.h"
#include "REFEncoding.h"
#include "REFBaseCodePageEncoding.h"
#include "REFDBCSCodePageEncoding.h"
#include "CharUnicodeInfo.h"

#define	UNKNOWN_CHAR_FLAG			(UCHAR)0x0
#define	UNICODE_REPLACEMENT_CHAR	(UCHAR)0xFFFD
#define	LEAD_BYTE_CHAR				(UCHAR)0xFFFE	// For lead bytes

namespace BFX
{

////////////////////////////////////////////////////////////////////////////////
// REFDBCSCodePageEncoding

REFDBCSCodePageEncoding::REFDBCSCodePageEncoding(int nCodePage)
	: REFBaseCodePageEncoding(nCodePage, nCodePage)
{
	m_pMapBytesToUnicode = NULL;
	m_pMapUnicodeToBytes = NULL;
	m_pMapCodePageCached = NULL;
}

REFDBCSCodePageEncoding::REFDBCSCodePageEncoding(int nCodePage, int nDataCodePage)
	: REFBaseCodePageEncoding(nCodePage, nDataCodePage)
{
	m_pMapBytesToUnicode = NULL;
	m_pMapUnicodeToBytes = NULL;
	m_pMapCodePageCached = NULL;
}

REFDBCSCodePageEncoding::~REFDBCSCodePageEncoding()
{
}

//
// Overrides
//
int REFDBCSCodePageEncoding::GetMaxByteCount(int nCharCount) const
{
	BFX_REQUIRE (nCharCount >= 0 && "Non-negative number required.");

	// Characters would be # of characters + 1 in case high surrogate is ? * max fallback
	long long lByteCount = (long long)nCharCount + 1;

	// 2 to 1 is worst case.  Already considered surrogate fallback
	lByteCount *= 2;

	BFX_ENSURE1 (lByteCount <= 0x7fffffff, "Too many characters. The resulting number of bytes is larger than what can be returned as an int.");

	return (int)lByteCount;
}

int REFDBCSCodePageEncoding::GetMaxCharCount(int nByteCount) const
{
	BFX_REQUIRE (nByteCount >= 0 && "Non-negative number required.");

	// DBCS is pretty much the same, but could have hanging high byte making extra ? and fallback for unknown
	long long lCharCount = ((long long)nByteCount + 1);

	BFX_ENSURE1 (lCharCount <= 0x7fffffff, "Too many bytes. The resulting number of chars is larger than what can be returned as an int.");

	return (int)lCharCount;
}

// GetByteCount
// Note: We start by assuming that the output will be the same as count.  Having
// an encoder or fallback may change that assumption
int REFDBCSCodePageEncoding::GetByteCount(const UCHAR* pChars, int nCount) const
{
	// Validate the parameters.
	BFX_REQUIRE ((pChars != NULL || nCount == 0) && "Null pointer disallowed.");
	BFX_REQUIRE (nCount >= 0 && "Non-negative number required.");

	CheckMemorySection();

	// prepare our end
	int nByteCount = 0;
	const UCHAR* pCharEnd = pChars + nCount;

	// For fallback
	bool bFallingBack = false;

	// Now we may have fallback pChar already (from the encoder)

	// We have to use fallback method.
	UCHAR ch;
	while ((ch = bFallingBack ? '?' : '\0') != 0 || pChars < pCharEnd)
	{
		bFallingBack = false;

		// First unwind any fallback
		if (ch == 0)
		{
			// No fallback, just get next char
			ch = *pChars;
			pChars++;
		}

		// get byte for this char
		UINT16 sTemp = m_pMapUnicodeToBytes[ch];

		// Check for fallback, this'll catch surrogate pairs too.
		if (sTemp == 0 && ch != (UCHAR)0)
		{
			// Get Fallback
			bFallingBack = true;
			pChars ++;

			continue;
		}

		// We'll use this one
		nByteCount++;
		if (sTemp >= 0x100)
			nByteCount++;
	}

	return nByteCount;
}

int REFDBCSCodePageEncoding::GetBytes(const UCHAR* pChars, int nCharCount, OUT BYTE* pBytes, int nByteCount) const
{
	// Validate the parameters.
	BFX_REQUIRE (pChars != NULL && pBytes != NULL && "Null reference of argument disallowed.");
	BFX_REQUIRE (nCharCount >= 0 && nByteCount >= 0 && "Non-negative number required.");

	CheckMemorySection();

	// For fallback
	bool bFallingBack = false;

	// prepare our end
	const UCHAR* pCharEnd = pChars + nCharCount;
	const UCHAR* pCharStart = pChars;
	BYTE* pByteStart = pBytes;
	BYTE* pByteEnd = pBytes + nByteCount;

	// Go ahead and do it, including the fallback.
	UCHAR ch;
	while ((ch = bFallingBack ? '?' : '\0') != 0 || pChars < pCharEnd)
	{
		bFallingBack = false;

		// First unwind any fallback
		if (ch == 0)
		{
			// No fallback, just get next char
			ch = *pChars;
			pChars++;
		}

		// get byte for this char
		UINT16 sTemp = m_pMapUnicodeToBytes[ch];

		// Check for fallback, this'll catch surrogate pairs too.
		if (sTemp == 0 && ch != (UCHAR)0)
		{
			// Get Fallback
			bFallingBack = true;
			pChars ++;

			continue;
		}

		// We'll use this one (or two)
		// Bounds check

		// Go ahead and add it, lead byte 1st if necessary
		if (sTemp >= 0x100)
		{
			if (pBytes + 1 >= pByteEnd)
			{
				BFX_ASSERT(!bFallingBack);

				// didn't use this char, we'll throw or use buffer
				BFX_ASSERT(pChars > pCharStart);	// Expected chars to have advanced (double byte case)");
				pChars--;                                        // don't use last char

				BFX_ENSURE(pChars != pCharStart);						// throw ?
				break;                                              // don't throw, stop
			}

			*pBytes = (BYTE)(sTemp >> 8);
			pBytes++;
		}
		// Single byte
		else if (pBytes >= pByteEnd)
		{
			BFX_ASSERT(!bFallingBack);

			// didn't use this char, we'll throw or use buffer
			BFX_ASSERT(pChars > pCharStart);	// Expected chars to have advanced (single byte case)");
			pChars--;                                       // don't use last char

			BFX_ENSURE(pChars != pCharStart);						// throw ?
			break;                                              // don't throw, stop
		}

		*pBytes = (BYTE)(sTemp & 0xff);
		pBytes++;
	}

	return (int)(pBytes - pByteStart);
}

int REFDBCSCodePageEncoding::GetCharCount(const BYTE* pBytes, int nCount, REFDecoder* pDecoder) const
{
	// Validate the parameters.
	BFX_REQUIRE (pBytes != NULL && "Null pointer disallowed");
	BFX_REQUIRE (nCount >= 0 && "Non-negative number required.");

	CheckMemorySection();

	// Get our fallback
	REF<REFDecoderFallbackBuffer> pFallbackBuffer;

	// Fix our decoder
	DBCSDecoder* pDbcsDecoder = (DBCSDecoder*) pDecoder;

	// We'll need to know where the end is
	const BYTE* pByteEnd = pBytes + nCount;
	int nCharCount = nCount;	// Assume 1 char / byte

	// Shouldn't have anything in fallback buffer for GetCharCount
	// (don't have to check m_throwOnOverflow for count)
	BFX_ASSERT1(pDbcsDecoder == NULL || !pDbcsDecoder->HasFallbackBuffer() || pDbcsDecoder->GetFallbackBuffer()->GetRemaining() == 0,
		"Expected empty fallback buffer at start");

	// If we have a left over byte, use it
	if (pDbcsDecoder != NULL && pDbcsDecoder->m_byteLeftOver > 0)
	{
		// We have a left over byte?
		if (nCount == 0)
		{
			// No input though
			if (!pDbcsDecoder->IsFlushRequired())
			{
				// Don't have to flush
				return 0;
			}

			BFX_ASSERT1(pFallbackBuffer == NULL, "Expected empty fallback buffer");
			pFallbackBuffer = pDbcsDecoder->GetFallbackBuffer();
			pFallbackBuffer->Initialize(pBytes, NULL);

			SequenceT<BYTE> bytesUnknown;
			bytesUnknown.Append((BYTE)pDbcsDecoder->m_byteLeftOver);
			return pFallbackBuffer->Fallback(bytesUnknown, pBytes);
		}

		// Get our full info
		int iBytes = pDbcsDecoder->m_byteLeftOver << 8;
		iBytes |= (*pBytes);
		pBytes++;

		// This is either 1 known char or fallback
		// Already counted 1 char
		// Look up our bytes
		UCHAR cDecoder = m_pMapBytesToUnicode[iBytes];
		if (cDecoder == 0 && iBytes != 0)
		{
			// Deallocate preallocated one
			nCharCount--;

			// We'll need a fallback
			BFX_ASSERT1(pFallbackBuffer == NULL, "Expected empty fallback buffer for unknown pair");
			pFallbackBuffer = pDbcsDecoder->GetFallbackBuffer();
			pFallbackBuffer->Initialize(pByteEnd - nCount, NULL);

			// Do fallback, we know there're 2 bytes
			SequenceT<BYTE> bytesUnknown;
			bytesUnknown.Append((BYTE)(iBytes >> 8));
			bytesUnknown.Append((BYTE)iBytes);
			nCharCount += pFallbackBuffer->Fallback(bytesUnknown, pBytes);
		}
		// else we already reserved space for this one.
	}

	// Loop, watch out for fallbacks
	while (pBytes < pByteEnd)
	{
		// Faster if don't use *pBytes++;
		int iBytes = *pBytes;
		pBytes++;
		UCHAR ch = m_pMapBytesToUnicode[iBytes];

		// See if it was a double byte character
		if (ch == LEAD_BYTE_CHAR)
		{
			// Its a lead byte
			nCharCount--; // deallocate preallocated lead byte
			if (pBytes < pByteEnd)
			{
				// Have another to use, so use it
				iBytes <<= 8;
				iBytes |= *pBytes;
				pBytes++;
				ch = m_pMapBytesToUnicode[iBytes];
			}
			else
			{
				// No input left
				if (pDbcsDecoder == NULL || pDbcsDecoder->IsFlushRequired())
				{
					// have to flush anyway, set to unknown so we use fallback in a 'sec
					nCharCount++; // reallocate deallocated lead byte
					ch = UNKNOWN_CHAR_FLAG;
				}
				else
				{
					// We'll stick it in decoder
					break;
				}
			}
		}

		// See if it was unknown.
		// Unknown and known chars already allocated, but fallbacks aren't
		if (ch == UNKNOWN_CHAR_FLAG && iBytes != 0)
		{
			if (pFallbackBuffer == NULL)
			{
				if (pDbcsDecoder == NULL)
					pFallbackBuffer = GetDecoderFallback()->CreateFallbackBuffer();
				else
					pFallbackBuffer = pDbcsDecoder->GetFallbackBuffer();
				pFallbackBuffer->Initialize(pByteEnd - nCount, NULL);
			}

			// Do fallback
			nCharCount--;    // Get rid of preallocated extra char
			SequenceT<BYTE> bytesUnknown;
			if (iBytes < 0x100)
				bytesUnknown.Append((BYTE)iBytes);
			else
			{
				bytesUnknown.Append((BYTE)(iBytes >> 8));
				bytesUnknown.Append((BYTE)iBytes);
			};
			nCharCount += pFallbackBuffer->Fallback(bytesUnknown, pBytes);
		}
	}

	// Shouldn't have anything in fallback buffer for GetChars
	BFX_ASSERT1(pDbcsDecoder == NULL || !pDbcsDecoder->HasFallbackBuffer() || pDbcsDecoder->GetFallbackBuffer()->GetRemaining() == 0,
		"Expected empty fallback buffer at end");

	// Return our count
	return nCharCount;
}

int REFDBCSCodePageEncoding::GetChars(const BYTE* pBytes, int nByteCount, OUT UCHAR* pChars, int nCharCount, REFDecoder* pDecoder) const
{
	// Validate the parameters.
	BFX_REQUIRE (pChars != NULL && pBytes != NULL && "Null pointer is disallowed.");
	BFX_REQUIRE (nCharCount >= 0 && nByteCount >= 0 && "Non-negative number required.");

	CheckMemorySection();

	// We'll need to know where the end is
	const BYTE* pByteStart = pBytes;
	const BYTE* pByteEnd = pBytes + nByteCount;
	UCHAR* pCharStart = pChars;
	UCHAR* pCharEnd = pChars + nCharCount;
	bool bUsedDecoder = false;

	// Get our fallback
	REF<REFDecoderFallbackBuffer> pFallbackBuffer = NULL;
	// Fix our decoder
	DBCSDecoder* pDbcsDecoder = (DBCSDecoder*)pDecoder;

	// Shouldn't have anything in fallback buffer for GetChars
	BFX_ASSERT1(pDbcsDecoder == NULL || !pDbcsDecoder->HasFallbackBuffer() || pDbcsDecoder->GetFallbackBuffer()->GetRemaining() == 0,
		"Expected empty fallback buffer at start");

	// If we have a left over byte, use it
	if (pDbcsDecoder != NULL && pDbcsDecoder->m_byteLeftOver > 0)
	{
		// We have a left over byte?
		if (nByteCount == 0)
		{
			// No input though
			if (!pDbcsDecoder->IsFlushRequired())
			{
				// Don't have to flush
				return 0;
			}

			// Well, we're flushing, so use '?' or fallback fallback leftover byte
			BFX_ASSERT1(pFallbackBuffer == NULL, "Expected empty fallback");
			pFallbackBuffer = pDbcsDecoder->GetFallbackBuffer();
			pFallbackBuffer->Initialize(pBytes, pCharEnd);

			// If no room its hopeless, this was 1st fallback
			SequenceT<BYTE> bytesUnknown;
			bytesUnknown.Append((BYTE)pDbcsDecoder->m_byteLeftOver);
			if (!pFallbackBuffer->Fallback(bytesUnknown, pBytes, INOUT pChars))
			{
				BFX_ENSURE(false);
			}

			pDbcsDecoder->m_byteLeftOver = 0;

			// Done, return it
			return (int)(pChars-pCharStart);
		}

		// Get our full info
		int iBytes = pDbcsDecoder->m_byteLeftOver << 8;
		iBytes |= (*pBytes);
		pBytes++;

		// Look up our bytes
		UCHAR cDecoder = m_pMapBytesToUnicode[iBytes];
		if (cDecoder == UNKNOWN_CHAR_FLAG && iBytes != 0)
		{
			BFX_ASSERT1(pFallbackBuffer == NULL, "Expected empty fallback for two bytes");
			pFallbackBuffer = pDbcsDecoder->GetFallbackBuffer();
			pFallbackBuffer->Initialize(pByteEnd - nByteCount, pCharEnd);

			SequenceT<BYTE> bytesUnknown;
			bytesUnknown.Append((BYTE)(iBytes >> 8));
			bytesUnknown.Append((BYTE)iBytes);
			if (!pFallbackBuffer->Fallback(bytesUnknown, pBytes, INOUT pChars))
			{
				BFX_ENSURE(false);
			}
		}
		else
		{
			// Do we have output room?, hopeless if not, this is first char
			if (pChars >= pCharEnd)
			{
				BFX_ENSURE(false);
			}

			*(pChars++) = cDecoder;
		}
	}

	// Loop, paying attention to our fallbacks.
	while (pBytes < pByteEnd)
	{
		// Faster if don't use *bytes++;
		int iBytes = *pBytes;
		pBytes++;
		UCHAR c = m_pMapBytesToUnicode[iBytes];

		// See if it was a double byte character
		if (c == LEAD_BYTE_CHAR)
		{
			// Its a lead byte
			if (pBytes < pByteEnd)
			{
				// Have another to use, so use it
				iBytes <<= 8;
				iBytes |= *pBytes;
				pBytes++;
				c = m_pMapBytesToUnicode[iBytes];
			}
			else
			{
				// No input left
				if (pDbcsDecoder == NULL || pDbcsDecoder->IsFlushRequired())
				{
					// have to flush anyway, set to unknown so we use fallback in a 'sec
					c = UNKNOWN_CHAR_FLAG;
				}
				else
				{
					// Stick it in decoder
					bUsedDecoder = true;
					pDbcsDecoder->m_byteLeftOver = (BYTE)iBytes;
					break;
				}
			}
		}

		// See if it was unknown
		if (c == UNKNOWN_CHAR_FLAG && iBytes != 0)
		{
			if (pFallbackBuffer == NULL)
			{
				if (pDbcsDecoder == NULL)
					pFallbackBuffer = GetDecoderFallback()->CreateFallbackBuffer();
				else
					pFallbackBuffer = pDbcsDecoder->GetFallbackBuffer();
				pFallbackBuffer->Initialize(pByteEnd - nByteCount, pCharEnd);
			}

			// Do fallback
			SequenceT<BYTE> bytesUnknown;
			if (iBytes < 0x100)
				bytesUnknown.Append((BYTE)iBytes);
			else
			{
				bytesUnknown.Append((BYTE)(iBytes >> 8));
				bytesUnknown.Append((BYTE)iBytes);
			}
			if (!pFallbackBuffer->Fallback(bytesUnknown, pBytes, INOUT pChars))
			{
				// May or may not throw, but we didn't get these byte(s)
				BFX_ASSERT1(pBytes >= pByteStart + bytesUnknown.GetSize(), "Expected bytes to have advanced for fallback");
				pBytes -= bytesUnknown.GetSize();                   // didn't use these byte(s)
				pFallbackBuffer->ResetAll();                        // Didn't fall this back
				BFX_ENSURE(pBytes != pByteStart);					// throw?
				break;                                              // don't throw, but stop loop
			}
		}
		else
		{
			// Do we have buffer room?
			if (pChars >= pCharEnd)
			{
				// May or may not throw, but we didn't get these byte(s)
				BFX_ASSERT(pBytes > pByteStart);
				pBytes--;                               // unused byte
				if (iBytes >= 0x100)
				{
					BFX_ASSERT(pBytes > pByteStart);	// Expected bytes to have advanced for trail byte");
					pBytes--;                           // 2nd unused byte
				}
				BFX_ENSURE(pBytes != pByteStart);		// throw?
				break;                                  // don't throw, but stop loop
			}

			*(pChars++) = c;
		}
	}

	// We already stuck it in encoder if necessary, but we have to clear cases where nothing new got into decoder
	if (pDbcsDecoder != NULL)
	{
		// Clear it in case of MustFlush
		if (bUsedDecoder == false)
		{
			pDbcsDecoder->m_byteLeftOver = 0;
		}

		// Remember our count
		// TODO: pDbcsDecoder->m_nBytesUsed = (int)(pBytes - pByteStart);
	}

	// Shouldn't have anything in fallback buffer for GetChars
	BFX_ASSERT1(pDbcsDecoder == NULL || !pDbcsDecoder->HasFallbackBuffer() || pDbcsDecoder->GetFallbackBuffer()->GetRemaining() == 0,
		"Expected empty fallback buffer at end");

	// Return length of our output
	return (int)(pChars - pCharStart);
}

// MBCS data section:
//
// We treat each multibyte pattern as 2 bytes in our table.  If its a single byte, then the high byte
// for that position will be 0.  When the table is loaded, leading bytes are flagged with 0xFFFE, so
// when reading the table look up with each byte.  If the result is 0xFFFE, then use 2 bytes to read
// further data.  FFFF is a special value indicating that the unicode code is the same as the
// character code (this helps us support code points < 0x20).  FFFD is used as replacement character.
//
// Normal table:
// UCHAR*     -  Starting with MB code point 0.
//               FFFF indicates we are to use the multibyte value for our code point.
//               FFFE is the lead byte mark.  (This should only appear in positions < 0x100)
//               FFFD is the replacement (unknown character) mark.
//               2-20 means to advance the pointer 2-0x20 characters.
//               1 means that to advance to the multibyte position contained in the next char.
//               0 nothing special (I don't think its possible.)
//
// Table ends when multibyte position has advanced to 0xFFFF.
//
// Bytes->Unicode Best Fit table:
// UCHAR*     -  Same as normal table, except first wchar is byte position to start at.
//
// Unicode->Bytes Best Fit Table:
// UCHAR*     -  Same as normal table, except first wchar is char position to start at and
//               we loop through unicode code points and the table has the byte points that
//               corrospond to those unicode code points.
// We have a managed code page entry, so load our tables
//
void REFDBCSCodePageEncoding::LoadManagedCodePage()
{
	// Should be loading OUR code page
	BFX_ASSERT(m_pCodePage->CodePage == m_nDataTableCodePage);	// Expected to load data table code page

	// Make sure we're really a 1 byte code page
	BFX_ENSURE1 (m_pCodePage->ByteCount == 2, "No data is available for current encoding.");
	// Remember our unknown bytes & chars
	UINT16	nBytesUnknown	= m_pCodePage->ByteReplace;
	// UCHAR	charUnknown		= m_pCodePage->UnicodeReplace;

	// Is our replacement bytesUnknown a single or double byte character?
	int	nByteCountUnknown = 1;
	if (nBytesUnknown > 0xff)
		nByteCountUnknown++;

	// We use fallback encoder, which uses ?, which so far all of our tables do as well
	BFX_ASSERT(nBytesUnknown == 0x3f);	// Expected 0x3f (?) as unknown byte character");

	// Get our mapped section (bytes to allocate = 2 bytes per 65536 Unicode chars + 2 bytes per 65536 DBCS chars)
	// Plus 4 byte to remember CP # when done loading it. (Don't want to get IA64 or anything out of alignment)
	// TODO: get shared memory.
	BYTE* pMemorySection = GetSharedMemory(65536 * 2 * 2 + 4);

	m_pMapBytesToUnicode = (UCHAR*)pMemorySection;
	m_pMapUnicodeToBytes = (UINT16*)(pMemorySection + 65536 * 2);
	m_pMapCodePageCached = (int*)(pMemorySection + 65536 * 2 * 2);

	// If its cached (& filled in) we don't have to do anything else
	if (*m_pMapCodePageCached != 0)
	{
		// Expected mapped section cached page flag to be set to data table or regular code page.
	
		// Special case for GB18030 because it mangles its own code page after this function
		BFX_ASSERT(*m_pMapCodePageCached == m_nDataTableCodePage);	// out of memory???

		// If its cached (& filled in) we don't have to do anything else
		return;
	}

	// Need to read our data file and fill in our section.
	// WARNING: Multiple code pieces could do this at once (so we don't have to lock machine-wide)
	//          so be careful here.  Only stick legal values in here, don't stick temporary values.

	// Move to the beginning of the data section
	UCHAR* pData = (UCHAR*)&(m_pCodePage->FirstDataWord);

	// We start at bytes position 0
	int nBytePosition = 0;
	int nUseBytes = 0;

	while (nBytePosition < 0x10000)
	{
		// Get the next byte
		UCHAR ch = *pData;
		pData++;

		// build our table:
		if (ch == 1)
		{
			// Use next data as our byte position
			nBytePosition = (int)(*pData);
			pData++;
			continue;
		}
		else if (ch < 0x20 && ch > 0)
		{
			// Advance ch characters
			nBytePosition += ch;
			continue;
		}
		else if (ch == 0xFFFF)
		{
			// Same as our nBytePosition
			nUseBytes = nBytePosition;
			ch = (UCHAR)nBytePosition;
		}
		else if (ch == LEAD_BYTE_CHAR) // 0xfffe
		{
			// Lead byte mark
			BFX_ASSERT(nBytePosition < 0x100);	// expected lead byte to be < 0x100
			nUseBytes = nBytePosition;
			// ch stays 0xFFFE
		}
		else if (ch == UNICODE_REPLACEMENT_CHAR)
		{
			// Replacement char is already done
			nBytePosition++;
			continue;
		}
		else
		{
			// Use this character
			nUseBytes = nBytePosition;
		}

		// We may need to clean up the selected character & position
		if (CleanUpBytes(nUseBytes))
		{
			// Use this selected character at the selected position, don't do this if not supposed to.
			if (ch != LEAD_BYTE_CHAR)
			{
				// Don't do this for lead byte marks.
				m_pMapUnicodeToBytes[ch] = (UINT16)nUseBytes;
			}
			m_pMapBytesToUnicode[nUseBytes] = ch;
		}
		nBytePosition++;
	}

	// See if we have any clean up junk to do
	CleanUpEndBytes(m_pMapBytesToUnicode);

	// We're done with our mapped section, set our flag so others don't have to rebuild table.
	// We only do this if we're flagging(using) the data table as our primary mechanism

	*m_pMapCodePageCached =	m_nDataTableCodePage;
}

// Returns a Decoder object for this encoding. The returned object can be used to decode a sequence of bytes into a sequence of characters.
// Contrary to the GetChars family of methods, a Decoder can convert partial sequences of bytes into partial sequences of characters
// by maintaining the appropriate state between the conversions.
REFDecoder* REFDBCSCodePageEncoding::GetDecoder() const
{
	REFDecoder* pDecoder = new DBCSDecoder(this);
	pDecoder->Autorelease();
	return pDecoder;
}

// Initializes the DBCS decoder.
REFDBCSCodePageEncoding::DBCSDecoder::DBCSDecoder(const REFEncoding* pEncoding)
	: REFDecoder(pEncoding), m_byteLeftOver(0)
{
}

REFDBCSCodePageEncoding::DBCSDecoder::~DBCSDecoder()
{
}

void REFDBCSCodePageEncoding::DBCSDecoder::Reset()
{
	m_byteLeftOver = 0;
	REFDecoder::Reset();
}

}	//	namespace BFX
